#ifdef KITSCHY_DEBUG_MEMORY 
#include "debug_memorymanager.h"
#endif

#ifdef WIN32
#include "windows.h"
#else
#include <sys/time.h>
#include <time.h>
#endif
#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "stdarg.h"
#include "math.h"
#include "assert.h"

#include "List.h"

#include "symbol.h"
#include "sort.h"
#include "ontology.h"
#include "featureterm.h"
#include "FTKBase.h"
#include "Ufeatureterm.h"
#include "AUfeatureterm.h"
#include "FT_refinement.h"
#include "FT_generalization.h"

#include "SpecialTerm.h"
#include "ST_floatInterval.h"

#include "psm.h"

#ifndef WIN32
struct timeval init_tick_count_value;

void setupTickCount()
{
	gettimeofday(&init_tick_count_value, NULL);
}

long GetTickCount()
{
	struct timeval now;
	gettimeofday(&now, NULL);
	struct timeval diff;
	diff.tv_sec = now.tv_sec - init_tick_count_value.tv_sec;
	diff.tv_usec = now.tv_usec - init_tick_count_value.tv_usec;
	if (diff.tv_usec < 0)
	{
		diff.tv_sec--;
		diff.tv_usec+=1000000;
	}
	return diff.tv_sec*1000 + diff.tv_usec/1000;
}
#endif




int main(void)
{
	int t_start,t_end;

#ifndef WIN32
	setupTickCount();
#endif

	Ontology *o=new Ontology();
	FTKBase *case_base=new FTKBase(o);
	FTKBase *domain_model=new FTKBase(o);

	domain_model->create_boolean_objects(o);
	case_base->uses(domain_model);

	printf("Stats 0: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());

	{

		domain_model->ImportNOOS("../NOOS/artificial-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/artificial-dm.noos",o);
		case_base->ImportNOOS("../NOOS/artificial-512.noos",o);

		ST_floatInterval::createSort(o);

/*
		domain_model->ImportNOOS("../NOOS/zoology-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/zoology-DM.noos",o);
		case_base->ImportNOOS("../NOOS/zoology-cases-101.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/soybean-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/soybean-dm.noos",o);
		case_base->ImportNOOS("../NOOS/soybean-cases-307.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/sponge-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/sponge-dm.noos",o);
//		case_base->ImportNOOS("../NOOS/sponge-cases-503.noos",o);
//		case_base->ImportNOOS("../NOOS/sponge-cases-280.noos",o);
//		case_base->ImportNOOS("../NOOS/sponge-cases-120.noos",o);
		case_base->ImportNOOS("../NOOS/sponge-cases-test.noos",o);
*/

/*
//      OLD FILES: --------------------------------------------------------------------
		domain_model->ImportNOOS("../NOOS/toxicology-eva/toxicology-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/toxicology-eva/toxicology-dm.noos",o);
		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-descriptions.noos",o);
//		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-descriptions-50.noos",o);
		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-problems.noos",o);
		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-cases-502.noos",o);
//		case_base->ImportNOOS("../NOOS/toxicology-eva/toxicology-cases-50.noos",o);
*/

/*
//      NEW FILES: --------------------------------------------------------------------
		domain_model->ImportNOOS("../NOOS/toxic-eva-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/toxic-eva-dm.noos",o);
//		case_base->ImportNOOS("../NOOS/toxic-eva-cases-10.noos",o);
//		case_base->ImportNOOS("../NOOS/toxic-eva-cases-50.noos",o);
		case_base->ImportNOOS("../NOOS/toxic-eva-cases-100.noos",o);
//		case_base->ImportNOOS("../NOOS/toxic-eva-cases-371.noos",o);
*/

/*
		domain_model->ImportNOOS("../NOOS/family-ontology.noos",o);
		domain_model->ImportNOOS("../NOOS/family-dm.noos",o);
		case_base->ImportNOOS("../NOOS/family-cases-12.noos",o);
//		case_base->ImportNOOS("../NOOS/family-cases-12-sets.noos",o);
*/
		printf("Stats 1: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());

		printf("There are %i + %i undefined terms.\n",domain_model->get_n_undefined_terms(),case_base->get_n_undefined_terms());

		t_start=GetTickCount();

		{
			Path *dp=new Path,*sp=new Path;
			Prediction *solution;

			List<FeatureTerm> *cases;
			FeatureTerm *problem,*problem_description,*problem_solution;

			dp->Add(new Symbol("description"));
			sp->Add(new Symbol("solution"));
//			sp->Add(new Symbol("order"));
//			sp->Add(new Symbol("m-rats"));

			cases=case_base->SearchFT(o->get_sort("artificial-data-problem"));
//			cases=case_base->SearchFT(o->get_sort("zoo-problem"));
//			cases=case_base->SearchFT(o->get_sort("sponge-problem"));
//			cases=case_base->SearchFT(o->get_sort("soybean-problem"));
//			cases=case_base->SearchFT(o->get_sort("uncle-problem"));
//			cases=case_base->SearchFT(o->get_sort("toxic-problem"));

			/* Leave one out: */ 
			{
				int i;
				int size=cases->Length();
				int correct=0,incorrect=0;
				int pos;
				List<FeatureTerm> solutions;
				List<int> solutions_correct;
				List<int> solutions_incorrect;

//				for(i=0;i<1;i++) cases->Add(cases->ExtractIni());
				for(i=0;i<size;i++) {
//				i=0;{
					problem=cases->ExtractIni();
					problem_description=problem->featureValue("description");
//					problem_solution=problem->featureValue("solution");
					problem_solution=problem->featureValueQuick("solution");
//					problem_solution=problem_solution->featureValue("order");
//					problem_solution=problem_solution->featureValue("m-rats");


					// Execute rLID3 till the end:
//					solution=refinement_LID3(problem_description,cases,dp,sp,o,domain_model,0,0,1 ); /* GAIN */ 
					solution=refinement_LID3(problem_description,cases,dp,sp,o,domain_model,1,0,1); /* RLDM */ 
									
					// Execute rLID2 till the end:
//					solution=refinement_LID2(problem_description,cases,dp,sp,o,domain_model,0,0,1 ); /* GAIN */ 
//					solution=refinement_LID2(problem_description,cases,dp,sp,o,domain_model,1,0,1); /* RLDM */ 

//					solution=eva_LID(problem_description,cases,dp,sp,o,domain_model,1,0,1); /* RLDM */ 

					// Execute rLID till the end:
//					solution=refinement_LID(problem_description,cases,dp,sp,o,domain_model,0,0,1); /* GAIN */ 
//					solution=refinement_LID(problem_description,cases,dp,sp,o,domain_model,1,0,1); /* RLDM */ 
//					solution=refinement_LID(problem_description,cases,dp,sp,o,domain_model,2,0,1); /* ENTROPY */ 

					// Execute rLID only if 5 precedents or more:
//					solution=refinement_LID(problem_description,cases,dp,sp,o,domain_model,0,0,5); /* GAIN */ 
//					solution=refinement_LID(problem_description,cases,dp,sp,o,domain_model,1,0,5); /* RLDM */ 
		
//					solution=refinement_LID(problem_description,cases,dp,sp,o,domain_model,-1,1,1); /* RANDOM */ 			

//					solution=refinement_LID(problem_description,cases,dp,sp,o,domain_model,1,2,1); /* RANDOM-PONDERATED */ 

					if (solution!=0 && *(solution->solutions[0])==*problem_solution) {
						printf("OK\n\n");

						correct++;
						pos=solutions.Position(problem_solution);
						if (pos==-1) {
							solutions.Add(new FeatureTerm(problem_solution));
							solutions_correct.Add(new int(1));
							solutions_incorrect.Add(new int(0));
						} else {
							(*(solutions_correct[pos]))++;
						} /* if */ 
					} else {
						printf("Fail\n\n");

						incorrect++;
						pos=solutions.Position(problem_solution);
						if (pos==-1) {
							solutions.Add(new FeatureTerm(problem_solution));
							solutions_correct.Add(new int(0));
							solutions_incorrect.Add(new int(1));
						} else {
							(*(solutions_incorrect[pos]))++;
						} /* if */ 
					} /* if */ 

					delete solution;
					delete problem_description;
//					delete problem_solution;

					cases->Add(problem);

					fflush(0);
				} /* for */ 

				printf("\nFinal results:\n");
				printf("Accuracy: %g%%  (%i %i)\n",float(100*correct)/float(correct+incorrect),correct,incorrect);
				printf("\nIndividual class results:\n");
				{
					int i;
					char *s;

					for(i=0;i<solutions.Length();i++) {
						s=solutions[i]->toStringNOOS();
						printf("%s  %i %i\n",s,*(solutions_correct[i]),*(solutions_incorrect[i]));
						delete []s;
					} /* for */ 
				}
				printf("\n");
	
			}

			cases->ExtractAll();
			delete cases;

			delete dp;
			delete sp;

		}

		t_end=GetTickCount();

		printf("Time taken: %i\n",t_end-t_start);

		printf("Stats 2: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());
	}

	delete case_base;
	delete domain_model;

	printf("Stats 3: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());

	delete o;

	printf("Stats 4: %i %i\n",Symbol::stats_nSymbols(),Symbol::stats_nSymbolReferences());
	Symbol::stats_printSymbolStats();

	Symbol::reset();

	return 0;
} /* main */ 



